#ifdef WWWPAL
#include "HTRobMan.h"
#include "RobotXGMML.h"
#include "XGMMLGen.h"
#include "XGMML_DTD.h"
#include "RobotFunctions.h"

#define PUT_CHAR(c)	(*me->isa->put_character)(me, c)
#define PUT_STR(s)	(*me->isa->put_string)(me, s)
#define PUT_BLOCK(s,l)	(*me->isa->put_block)(me, s, l)
#define START(e,p,v)	(*me->isa->start_element)(me, e, p, v)
#define END(e)		(*me->isa->end_element)(me, e)
#define FREE_TARGET	(*me->isa->_free)(me)

#define MAX_DIGITS 15

struct _HTStructured {
    const HTStructuredClass *	isa;
    /* ... */
};

PRIVATE void
rob_write_xgmml_head(Robot * mr,HTStructured *me);
PRIVATE void
rob_write_start_xgmml_graph(Robot * mr, HTStructured *me);
PRIVATE void
rob_write_end_xgmml_graph(Robot *mr, HTStructured *me);
PRIVATE void
rob_write_xgmml_nodes(Robot * mr,HTStructured *me);
PRIVATE void
rob_write_xgmml_edges(Robot * mr,HTStructured *me);

PUBLIC void
get_xgmml_graph_robot(Robot * mr,FILE *fp)
{
    HTStructured * me = XGMMLGenerator(NULL,NULL,NULL,NULL,
				       HTFWriter_new(NULL, fp, NO));
    rob_write_xgmml_head(mr,me);
    rob_write_start_xgmml_graph(mr,me);
    rob_write_xgmml_nodes(mr,me);
    rob_write_xgmml_edges(mr,me);
    rob_write_end_xgmml_graph(mr,me);
    FREE_TARGET;
}

PRIVATE void
rob_write_xgmml_head(Robot * mr,HTStructured *me)
{
}

PRIVATE void
rob_write_start_xgmml_graph(Robot * mr, HTStructured *me)
{
    BOOL present[XGMML_GRAPH_ATTRIBUTES];
    const char*  value[XGMML_GRAPH_ATTRIBUTES];

    memset((void *) present, '\0', XGMML_GRAPH_ATTRIBUTES);

    present[XGMML_GRAPH_DIRECTED] = YES;
    value[XGMML_GRAPH_DIRECTED] = "1";

    present[XGMML_GRAPH_ROOTNODE] = YES;
    value[XGMML_GRAPH_ROOTNODE] = "1";	

    START(XGMML_GRAPH, present,value);
}



PRIVATE void
rob_write_end_xgmml_graph(Robot *mr, HTStructured *me)
{
    END(XGMML_GRAPH);
}

PRIVATE void
rob_write_xgmml_attributes(HTStructured *me,HyperDoc *hd)
{
    HTParentAnchor *anchor = hd->anchor;
    HTFormat nformat = HTAnchor_format(anchor);
    const char *title = HTAnchor_title(anchor);
    /*char *ntitle = clean_string(hd->title);*/
    char *ntitle = HTEscape_nonascii(hd->title);
    char *mtype = HTAtom_name((HTAtom *)nformat);
    long int lsize = HTAnchor_length(anchor);
    const time_t t = HTAnchor_lastModified(anchor);
    char *date = ctime(&t);
    char mcode[MAX_DIGITS], msize[MAX_DIGITS];
    char *keyw =  HTAssocList_findObject(HTAnchor_meta(anchor),"keywords");

    BOOL present[XGMML_ATT_ATTRIBUTES];
    const char*  value[XGMML_ATT_ATTRIBUTES];



/*    if(!title && !ntitle && lsize < 0) {
	printf(" No att to CODE %d\n",hd->code);
	return;
    }*/

    if(hd->code < 0)
	return;

    memset((void *) present, '\0', XGMML_ATT_ATTRIBUTES);

    sprintf(mcode,"%d",hd->code);

    if(hd->code == 200) {
	sprintf(msize,"%ld",lsize);

	/*if(!ntitle)
	    ntitle = clean_string((char *)title);*/
	if(!ntitle)
	    ntitle = HTEscape_nonascii((char *)title);

	date[strlen(date)-1]='\0';
	
	present[XGMML_ATT_NAME] = YES;
	value[XGMML_ATT_NAME] = "title";
	present[XGMML_ATT_VALUE] = YES;
	value[XGMML_ATT_VALUE] = ntitle ? ntitle : "No title";
	
	START(XGMML_ATT, present,value);
	END(XGMML_ATT);
	if(ntitle)
	    HT_FREE(ntitle);

	present[XGMML_ATT_NAME] = YES;
	value[XGMML_ATT_NAME] = "mime";
	present[XGMML_ATT_VALUE] = YES;
	value[XGMML_ATT_VALUE] = mtype;
	
	START(XGMML_ATT, present,value);
	END(XGMML_ATT);

	present[XGMML_ATT_NAME] = YES;
	value[XGMML_ATT_NAME] = "size";
	present[XGMML_ATT_VALUE] = YES;
	value[XGMML_ATT_VALUE] = msize;

	START(XGMML_ATT, present,value);
	END(XGMML_ATT);

	present[XGMML_ATT_NAME] = YES;
	value[XGMML_ATT_NAME] = "date";
	present[XGMML_ATT_VALUE] = YES;
	value[XGMML_ATT_VALUE] = date;
	
	START(XGMML_ATT, present,value);
	END(XGMML_ATT);

	if(keyw && keyw[0]!='\0') {
	    char *nkeyw = HTEscape_nonascii(keyw);
	    present[XGMML_ATT_NAME] = YES;
	    value[XGMML_ATT_NAME] = "keywords";
	    present[XGMML_ATT_VALUE] = YES;
	    value[XGMML_ATT_VALUE] = nkeyw;
	
	    START(XGMML_ATT, present,value);
	    END(XGMML_ATT);
	    if(nkeyw)
		HT_FREE(nkeyw);
	}
    }
    present[XGMML_ATT_NAME] = YES;
    value[XGMML_ATT_NAME] = "code";
    present[XGMML_ATT_VALUE] = YES;
    value[XGMML_ATT_VALUE] = mcode;

    START(XGMML_ATT, present,value);
    END(XGMML_ATT);
}

PRIVATE void
rob_write_xgmml_node(HTStructured *me,HyperDoc *hd)
{
    HTParentAnchor *anchor = hd->anchor;
    int weight = HTAnchor_length(anchor);
    char *uri  = HTAnchor_address((HTAnchor *)anchor);
    char *nuri = uri ? HTEscape_nonascii(uri) : NULL;
    BOOL present[XGMML_NODE_ATTRIBUTES];
    const char*  value[XGMML_NODE_ATTRIBUTES];
    char mid[MAX_DIGITS],mweight[MAX_DIGITS];
    sprintf(mid,"%d",hd->index);
    sprintf(mweight,"%d",weight);

    memset((void *) present, '\0', XGMML_NODE_ATTRIBUTES);

    present[XGMML_NODE_ID] = YES;
    value[XGMML_NODE_ID] = mid;

    present[XGMML_NODE_LABEL] = YES;
    value[XGMML_NODE_LABEL] = nuri;

    present[XGMML_NODE_WEIGHT] = YES;
    value[XGMML_NODE_WEIGHT] = mweight;

    START(XGMML_NODE,present,value);
    rob_write_xgmml_attributes(me,hd);
    END(XGMML_NODE);

    HT_FREE(uri);    HT_FREE(nuri);
}


PRIVATE void
rob_write_xgmml_nodes(Robot * mr,HTStructured *me)
{
    HTList * cur = mr->hyperdoc;
    HyperDoc * pres;
    while((pres = (HyperDoc *) HTList_nextObject(cur)) != NULL) {

	if(!(pres->code >= 300 && pres->code < 400))
	    rob_write_xgmml_node(me,pres);
    }
}

PRIVATE char *
get_link_attribute(HTLink *link)
{
    HTLinkType linktype = HTLink_type(link);
    char * str = linktype ? HTAtom_name(linktype) : NULL;
    return str;
}

PRIVATE void
rob_write_xgmml_edge_attribute(HTStructured *me, HTLink *link)
{
    char *satt = get_link_attribute(link);
    BOOL present[XGMML_ATT_ATTRIBUTES];
    const char*  value[XGMML_ATT_ATTRIBUTES];
    memset((void *) present, '\0', XGMML_ATT_ATTRIBUTES);

    if(satt && strcasecomp(satt,"referer")) {
	present[XGMML_ATT_VALUE] = YES;
	value[XGMML_ATT_VALUE] = satt;
	START(XGMML_ATT,present,value);
	END(XGMML_ATT);
    }
/*    if(stranc) {
	present[XGMML_ATT_NAME] = YES;
	value[XGMML_ATT_NAME] = "sanchor";
	present[XGMML_ATT_VALUE] = YES;
	value[XGMML_ATT_VALUE] = stranc;
	START(XGMML_ATT,present,value);
	END(XGMML_ATT);
    }*/
}

PRIVATE void
rob_write_xgmml_edge(HTStructured *me, HyperDoc *hds, 
		     HyperDoc *hdt, HTLink *link, char *stranc)
{
    char msource[MAX_DIGITS];
    char mtarget[MAX_DIGITS];
    BOOL present[XGMML_EDGE_ATTRIBUTES];
    const char*  value[XGMML_EDGE_ATTRIBUTES];
    char *cstr = NULL;
    memset((void *) present, '\0', XGMML_EDGE_ATTRIBUTES);
    sprintf(msource,"%d",hds->index);
    sprintf(mtarget,"%d",hdt->index);

    present[XGMML_EDGE_SOURCE] = YES;
    value[XGMML_EDGE_SOURCE] = msource;
    present[XGMML_EDGE_TARGET] = YES;
    value[XGMML_EDGE_TARGET] = mtarget;
    if(stranc && stranc[0]!='0') {
	/*cstr = clean_string(stranc);*/
	cstr = HTEscape_nonascii(stranc);
	present[XGMML_EDGE_LABEL] = YES;
	value[XGMML_EDGE_LABEL] = cstr;
    }
    START(XGMML_EDGE,present,value);
    rob_write_xgmml_edge_attribute(me,link);
    END(XGMML_EDGE);
    HT_FREE(cstr);
} 

PRIVATE void
rob_write_xgmml_edges(Robot *mr, HTStructured *me)
{
    HTList * cur = mr->hyperdoc;
    HyperDoc * hds;

    while((hds = (HyperDoc *) HTList_nextObject(cur)) != NULL) {
	HTAnchor * dest = NULL;
	HTParentAnchor *pdest = NULL;
	HyperDoc * hdd = NULL;
	HTAnchor * source = (HTAnchor *)hds->anchor;

	if(hds->code >=300 && hds->code < 400)
	    continue;

	if(hds->llinks && !HTList_isEmpty(hds->llinks))
	{
	    HTList * curln = hds->llinks;
	    LinkNode *linknode = NULL;
	    while((linknode = (LinkNode *) HTList_nextObject(curln)) != NULL) {
		char *stranc = linknode->stranc;
		HTLink *link = NULL;
		dest = linknode->dest;
		pdest  = HTAnchor_parent(HTAnchor_followMainLink(dest));
		link = pdest ? HTLink_find(source,(HTAnchor *)pdest) : NULL;
		hdd = pdest ? HTAnchor_document(pdest) : NULL;

		if(!hdd)
		    continue;

		if(hdd->code >=300 && hdd->code < 400) {
		    HTParentAnchor * ranchor = HTAnchor_parent(HTAnchor_followMainLink((HTAnchor *)hdd->anchor));
		    hdd = ranchor ? HTAnchor_document(ranchor) : NULL;
		    if(!hdd)
			continue;
		    else if (hdd->code >=300 && hdd->code < 400)
		    {
			ranchor = HTAnchor_parent(HTAnchor_followMainLink((HTAnchor *)hdd->anchor));
			hdd = ranchor ? HTAnchor_document(ranchor) : NULL;
			if(!hdd)
			    continue;
			if(hdd->code >=300 && hdd->code < 400)
			    continue;
		    }
		}

		if(hds->index != hdd->index) {
		    char *satt = link ? get_link_attribute(link) : NULL;
		    if(!satt || strcasecomp(satt,"made")) {
			rob_write_xgmml_edge(me,hds, hdd, link,stranc);
		    }
		}
	    }
	}
    }
}
#if 0
PRIVATE void
rob_write_xgmml_edges2(Robot *mr, HTStructured *me)
{
    HTList * cur = mr->hyperdoc;
    HyperDoc * pres;

    while((pres = (HyperDoc *) HTList_nextObject(cur)) != NULL) {
	HTParentAnchor *anchor = pres->anchor;
	HTParentAnchor * dest = (HTParentAnchor *)
	    HTAnchor_followMainLink((HTAnchor *) anchor);
	HTList *sublinks = HTAnchor_subLinks((HTAnchor *)anchor);
	HyperDoc * hd = HTAnchor_document(dest);
	HTLink * mlink = HTAnchor_mainLink((HTAnchor *) anchor);

	if(pres->code >= 300 && pres->code < 400)
	    continue;

	if(hd) {
	    if(pres->index != hd->index) {
		char *satt = get_link_attribute(mlink);
		if(!satt || strcasecomp(satt,"made")) {
		    rob_write_xgmml_edge(me, pres, hd, mlink);
		}
	    }
	}
	if(sublinks) {
	    HTLink * plink;
	    while((plink = (HTLink *) HTList_nextObject(sublinks)) != NULL) {
		HTAnchor *danchor = HTLink_destination(plink);
		hd = HTAnchor_document((HTParentAnchor *)danchor);
		if(hd) {
		    if(pres->index != hd->index) {
			char *satt = get_link_attribute(plink);
			if(!satt || strcasecomp(satt,"made")) {
			    rob_write_xgmml_edge(me, pres, hd, plink);
			}
		    }
		}
	    }
	}
    }
}
#endif
#endif







